(function() {
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(let x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
            || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function( callback ){
            let id = window.setTimeout(callback, 1000 / 60);
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

function getCanvasScale () {
    let ratio = 'devicePixelRatio';
    if (!(ratio in window)) return 1;
    return window[ratio] > 1 ? 2 : 1;
}

function getToScreenPosition(element) {
    let top = element.offsetTop || 0,
        left = element.offsetLeft || 0;
    if(element.offsetParent){
        let pPositon = getToScreenPosition(element.offsetParent);
        top += pPositon.top;
        left += pPositon.left;
    }
    return {
        top,
        left
    }
}

function canvasDrawImages(p) {
    this.canvansContainer = p.containerElement;
    this.childrenList = [];
    this.width = p.width;
    this.height = p.height;
    this.minScale = p.minScale || 0;
    this.maxScale = p.maxScale || 999;
    this.ontouchMove = p.ontouchMove;
    this.ontouchDown = p.ontouchDown;
    this.ontouchUp = p.ontouchUp;
    this.createCanvas(p.width, p.height, getCanvasScale());
    this.eventInit();
    this.draw();
}

canvasDrawImages.prototype.createCanvas = function (width, height, scaleFactor) {
    this.Stage = document.createElement('canvas');
    this.scaleFactor = scaleFactor;
    this.Stage.width = width * scaleFactor;
    this.Stage.height = height * scaleFactor;
    this.Stage.style.width = width + 'px';
    this.Stage.style.height = height + 'px';
    this.ctx = this.Stage.getContext("2d");
    this.canvansContainer.appendChild(this.Stage);
    this.baseVal = 750;
    this.position = getToScreenPosition(this.Stage);
};

canvasDrawImages.prototype.draw = function () {
    var s = this;
    this.clear();
    for(let n = 0, lgt = this.childrenList.length; n < lgt; n++){
        this.ctx.save();
        let child = this.childrenList[n];
        this.ctx.globalAlpha = child.alpha;
        let dwW = child.width ? child.width * child.scaleX * this.scaleFactor : 0,
            dwH = child.height ? child.height * child.scaleY * this.scaleFactor : 0;

        switch (child.type) {
            case 'IMG':
                var x = (child.x * this.scaleFactor  - child.anchorX / child.width * dwW),
                    y = (child.y * this.scaleFactor - child.anchorY / child.height * dwH);
                this.ctx.translate((x+(dwW/2)),(y+(dwH/2)));
                this.ctx.rotate(child.rotate);
                this.ctx.translate(-(x+(dwW/2)),-(y+(dwH/2)));
                this.ctx.drawImage(child.element, x, y, dwW, dwH);
                this.ctx.restore();
                child.vertexList = [];
                for(let i = 0; i < 4; i++){
                    //四点坐标
                    let x = Math.cos(child.vertexAngles[i] - child.rotate) * child.originLength * child.scaleX * this.scaleFactor + child.x * this.scaleFactor;
                    let y = child.y * this.scaleFactor - Math.sin(child.vertexAngles[i] - child.rotate) * child.originLength * this.scaleFactor  * child.scaleY;
                    child.vertexList.push({
                        x,
                        y
                    });

                    if(child.test){
                        this.ctx.beginPath();
                        this.ctx.arc(x, y, 20, 0, 2 * Math.PI);
                        this.ctx.fillStyle = "red";
                        this.ctx.fill();
                    }
                }
                break;

            case 'TEXT':
                this.fillText(child);
                break;
        }

    }

    s.requestAnmID = window.requestAnimationFrame(function () {
        s.draw();
    });
};

canvasDrawImages.prototype.fillText = function (child) {
    let s = this;
    this.ctx.beginPath();
    if(child.font){
        let font = child.font;
        if(s.scaleFactor > 1){
            font = font.replace(/\d+/g, function (val) {
                return Number(val) * s.scaleFactor;
            });
        }
        this.ctx.font = font;
    }

    if(child.textAlign)
        this.ctx.textAlign = child.textAlign;

    this.ctx.fillStyle = child.fillStyle ||  "#000000";

    let x = child.x * this.scaleFactor,
        y = child.y * this.scaleFactor,
        maxWidth = child.maxWidth * this.scaleFactor;

    let lineWidth = 0, lastSubStrIndex = 0,
        lineHeight = child.lineHeight * this.scaleFactor;

    for(let i = 0, lgt = child.text.length; i < lgt; i++){
        lineWidth += this.ctx.measureText(child.text[i]).width;
        if(lineWidth > maxWidth){
            i--;
            let lastLetter = child.text.substring(i - 1, i),
                nextLetter = child.text.substring(i, i + 1);
            //因为单词，单词不截断
            if(MK_checkEnglishLetter(lastLetter) && MK_checkEnglishLetter(nextLetter)){
                let currentStr = child.text.substring(lastSubStrIndex, i);
                let cutLetter = currentStr.match(/[^a-zA-Z]/g);
                if(cutLetter){
                    let blankIndex = currentStr.lastIndexOf(cutLetter[cutLetter.length - 1]);
                    if(blankIndex != -1){
                        i = blankIndex + 1 + lastSubStrIndex;
                    }
                }
            }

            this.ctx.fillText(child.text.substring(lastSubStrIndex, i), x, y);
            y += lineHeight;
            lineWidth = 0;
            lastSubStrIndex = i;
        }
        if(i == lgt - 1 ){
            this.ctx.fillText(child.text.substring(lastSubStrIndex, i + 1), x, y);
        }
    }

    this.ctx.restore();
};

canvasDrawImages.prototype.addLayer = function (imgSrc, x, y, width, height) {
    let s = this;
    let imgEle = new Image();
    imgEle.src = imgSrc;
    imgEle.onload = function () {
        //图片默认居中
        let child = new ImgMaterial(imgEle, typeof x === 'number' ? x : s.width / 2, typeof y === 'number' ? y :  s.height / 2, width, height);
        s.addChild(child);
    };
};

canvasDrawImages.prototype.addChild = function (child) {
    if(!this.checkChild(child)){
        child.parent = this;
        this.childrenList.push(child);
    }
};

canvasDrawImages.prototype.checkChild = function(child) {
    for(var i = 0, lgt = this.childrenList.length; i < lgt; i++){
        if(this.childrenList[i] == child)
            return true;
    }
    return false;
};

//删除
canvasDrawImages.prototype.removeChild = function (child) {
    for(var i = 0, lgt = this.childrenList.length; i < lgt; i++){
        if(this.childrenList[i] == child){
            this.childrenList.splice(i, 1);
        }
    }
};

//点击判定
canvasDrawImages.prototype.hit = function (event) {
    var s = this,
        lgt = this.childrenList.length;

    let clientX, clientY, clientXT, clientYT;
    if(event.targetTouches.length > 0){
        clientX = event.targetTouches[0].pageX - this.position.left;
        clientY = event.targetTouches[0].pageY - this.position.top;
        if(event.targetTouches[1]){
            clientXT = event.targetTouches[1].pageX - this.position.left;
            clientYT = event.targetTouches[1].pageY - this.position.top;
        }

        this.targetTouches = event.targetTouches;
    } else {
        clientX = event.clientX - this.position.left;
        clientY = event.clientY - this.position.y;

        this.targetTouches = [{
            pageX: event.clientX,
            pageY: event.clientY
        }]
    }

    for(let n = lgt - 1 ; n >= 0; n--){
        this.ctx.save();
        let child = this.childrenList[n];
        if(child.touchDisable)
            continue ;

        switch (child.type) {
            case 'IMG':
                if(this.checkRegion(child, clientX, clientY) || this.checkRegion(child, clientXT, clientYT)){
                    this.childrenList.splice(n, 1);
                    this.childrenList.push(child);
                    return child;
                }
                break
        }

    }

    return null;
};

//判定范围
canvasDrawImages.prototype.checkRegion = function(child, clientX, clientY) {
    let vertexList = child.vertexList;
    let hitNum = 0;
    for(let n = 0; n < 4; n++){
        let preNumber = n + 1 > 3 ? 0 : n + 1,
            hitY = clientY * this.scaleFactor,
            hitH = vertexList[preNumber].y - hitY,
            maxH = vertexList[preNumber].y - vertexList[n].y;

        let hitW, hitX;

        if(maxH == 0){
            hitX = vertexList[n].x;
        } else {
            hitW = (vertexList[preNumber].x - vertexList[n].x) / (vertexList[preNumber].y - vertexList[n].y) * hitH;
            hitX = vertexList[preNumber].x - hitW;
        }

        if(hitX <= clientX * this.scaleFactor){
            var minX, maxX, minY, maxY;

            if(vertexList[preNumber].x > vertexList[n].x){
                maxX = vertexList[preNumber].x;
                minX = vertexList[n].x;
            } else {
                maxX = vertexList[n].x;
                minX = vertexList[preNumber].x;
            }

            if(vertexList[preNumber].y > vertexList[n].y){
                maxY = vertexList[preNumber].y;
                minY = vertexList[n].y;
            } else {
                maxY = vertexList[n].y;
                minY = vertexList[preNumber].y;
            }

            if(hitX >= minX && hitX <= maxX && hitY >= minY && hitY <= maxY)
            hitNum++;
        }

    }
    //边碰撞监测， 偶数未碰撞，奇数碰撞
    return hitNum % 2 == 0 ? false : true;
};

canvasDrawImages.prototype.clear = function () {
    this.ctx.clearRect(0,0,this.width ,this.height);
    this.Stage.width = this.Stage.width;
};

canvasDrawImages.prototype.destroy = function () {
    this.clear();
    if(this.requestAnmID)
        window.cancelAnimationFrame(this.requestAnmID);
};

canvasDrawImages.prototype.getChildIndex = function(child) {
    for(var i = 0, lgt = this.childrenList.length; i < lgt; i++){
        if(this.childrenList[i] == child)
            return i;
    }
    return null;
};

canvasDrawImages.prototype.setChildIndex = function(child, index){
    if(typeof index != 'number'){
        return false;
    }

    let realIndex = this.getChildIndex(child);

    if(realIndex === null)
        return false;

    let lgt = this.childrenList.length;
    if(index >= lgt){
        this.childrenList.splice(realIndex, 1);
        this.childrenList.push(child);
    } else {
        this.childrenList.splice(realIndex, 1);
        this.childrenList.splice(index, 0, child);
    }

    console.log(this.childrenList)
};

//canvas导出图片
canvasDrawImages.prototype.toDataURL =function () {
    return this.Stage.toDataURL(arguments);
};

canvasDrawImages.prototype.eventInit = function () {
    let s = this;
    this.mkEvent = MonkeyEventInit(this.Stage);
    this.hitLayer = this.childrenList.length > 0 ? this.childrenList[this.this.childrenList.length - 1] : null;
    this.mkEvent.down = function(e){
        s.hitLayer = myCanvasDraw.hit(e);
        if(typeof s.ontouchDown === 'function')
            s.ontouchDown(s.hitLayer);
    };

    this.mkEvent.up = function(e){
        if(typeof s.ontouchUp === 'function')
            s.ontouchUp(s.hitLayer);
    };

    this.mkEvent.move = function(v){
        if(!s.hitLayer)
            return;

        s.hitLayer.x += v.distanceX;
        s.hitLayer.y += v.distanceY;

        if(typeof s.ontouchMove === 'function')
            s.ontouchMove(s.hitLayer);
    };

    this.mkEvent.scale = function(v){
        if(!s.hitLayer)
            return;

        var scaleVal = s.hitLayer.scaleX +  s.baseVal / s.hitLayer.width * 0.005 * v.speed;
        if(scaleVal <= s.minScale || scaleVal >= s.maxScale){
            return;
        }

        s.hitLayer.scaleX = s.hitLayer.scaleY = scaleVal;
    };

    this.mkEvent.rotate = function(v){
        if(!s.hitLayer)
            return;

        s.hitLayer.rotate += v.speed * 1;
    }
};

//MK继承
function MK_Extend(SubClass, SuperClass){
    //原型链层级保持一致性
    let __prototype = function(){};
    __prototype.prototype = SuperClass.prototype;
    SubClass.prototype = new __prototype();
    SubClass.prototype.constructor = SubClass;
}


function ImgMaterial(imgEle, x, y, width, height) {
    this.type ="IMG";
    this.element = imgEle;
    this.x = x || 0;
    this.y = y || 0;
    this.width = width || imgEle.width;
    this.height = height || imgEle.height;
    this.scaleX = 1;
    this.scaleY = 1;
    this.anchorX = this.width / 2;
    this.anchorY = this.height / 2;
    this.rotate = 0;
    this.alpha = 1;
    this.originLength = Math.sqrt(Math.pow(this.anchorX,2) + Math.pow(this.anchorY,2));
    this.init();

}

ImgMaterial.prototype.init = function () {
    this.vertexAngles = [];
    this.vertexAngles.push(Math.atan(this.anchorY / this.anchorX));
    this.vertexAngles.push(Math.PI - this.vertexAngles[0]);
    this.vertexAngles.push(Math.PI + this.vertexAngles[0]);
    this.vertexAngles.push(Math.PI * 2  - this.vertexAngles[0]);
};

function TextMaterial(fillStyle, text, x, y, maxWidth, lineHeight) {
    this.type ="TEXT";
    this.text = text || '';
    this.fillStyle = fillStyle || '#000000';
    this.x = x || 0;
    this.y = y || 0;
    this.maxWidth = maxWidth;
    this.lineHeight = lineHeight;
    this.scaleX = 1;
    this.scaleY = 1;
    this.rotate = 0;
    this.alpha = 1;
}

TextMaterial.prototype.setFont = function (fontVal) {
    this.font = fontVal;
};

TextMaterial.prototype.setTextAlign = function (textAlign) {
    this.textAlign = textAlign;
};

function MK_checkEnglishLetter(str) {
    const strRegex = /^([a-zA-Z]+)$/;
    return strRegex.test(str);
}